//db.c

#include "db.h"

static	const char *pDb = "./emu.db";		//Inverter Table Position
static	sqlite3 *hdb = NULL;   				//EMU Database Handle

static	unsigned char EvtArry[EVT_MAXCOUNT];

static char *SqlAry[] = {
	"CREATE TABLE T_Invlist(Invt_Adr INTEGER,Cur_Tmpr INTEGER,Life_Power INTEGER,Cur_Watt INTEGER,Date INTEGER);",
	"CREATE TABLE T_Evtlist(Invt_Adr INTEGER,Event_Id INTEGER,Date INTEGER);",		
	"CREATE TABLE T_Statlist(Last_ConctTime INTEGER,Life_Worktime INTERGER,Totl_Invt_Counts INTEGER,Online_Invt_Counts INTEGER,SigStrth INTEGER);",		
	"CREATE TABLE T_FixInvlist(Invt_Adr INTEGER,Type INTERGER,FixTime INTEGER,Hard_Version INTEGER,Firm_Version INTEGER);",
	"CREATE TABLE T_Inerlist(FstStart INTEGER,FstSettime INTEGER,Power_Before_Today INTEGER,Power_Before_Week INTEGER,Power_Before_Month INTEGER,Life_Worktime_Before_ThisConnct INTEGER,This_ConctTime INTEGER);"
};

static char *T_init[] = {
	"INSERT INTO T_Invlist VALUES(100420010002,30,1000,150,strftime('%s','now','localtime'));",		//for test
	"INSERT INTO T_Invlist VALUES(100420010003,30,1000,150,strftime('%s','now','localtime'));", 	//for test

	"INSERT INTO T_Evtlist VALUES(100420010002,0000,strftime('%s','now','localtime'));",	//for test
	"INSERT INTO T_Evtlist VALUES(100420010002,0001,strftime('%s','now','localtime'));",	//for test

	"INSERT INTO T_Statlist VALUES(0,0,10,8,5);",	//for test

	"INSERT INTO T_FixInvlist VALUES(100420010002,200,strftime('%s','now','localtime'),17,17);",//for test
	"INSERT INTO T_FixInvlist VALUES(100420010003,200,strftime('%s','now','localtime'),17,17);",//for test

	"INSERT INTO T_Inerlist VALUES(1,1,0,0,0,0,strftime('%s','now','localtime'));"		//not for test
};

//****************************************************
static	int		Db_IsRecordExist(struct	PLC_Dat *pPLC_Dat_,enum TableName tablename_,unsigned char *pEvtAry_);
static	int 	Db_InsertRecord(struct PLC_Dat *pPLC_Dat_,enum TableName tablename_,unsigned char *pEvtAry_);
static	void	Db_Update_Init();
static	int		Db_open(const char *pdb_, sqlite3** hdb_);
static	int		Db_close(sqlite3* hdb_);
static	int		Db_ExecSql(sqlite3* hdb_,char * psql_);

/****************************************************/
//FuncName : Db_Init
//Description :
//	->Open DB
//	->Create Table
//	->Init Table
//Input : None
//Return :
//	->0 : Success
//	->-1: Failed
//SideEffect : 
//	->Every Function in this module should be called after this API
/****************************************************/
int		Db_Init()
{
	int _i;
	//printf("%s\n",__FUNCTION__);

#if 0	
	char _pSql[100] = {0};			//for test
	char **_dbResult;		
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;
#endif

	if(0 == access(pDb,F_OK))					//emu.db already exist
	{
		if(-1 == Db_open(pDb,&hdb)) 			//Open
		{
			printf("%s\n","DB open failer!");
			Db_close(hdb);
			return -1;
		}
	}
	else
	{
		if(-1 == Db_open(pDb,&hdb)) 			//Open
		{
			printf("%s\n","DB open failer!");
			Db_close(hdb);
			return -1;
		}	

		for(_i = 0;_i < sizeof(SqlAry)/sizeof(SqlAry[0]);_i++)	//Create Table
		{
			if(-1 == Db_ExecSql(hdb,SqlAry[_i])) 
			{
				Db_close(hdb);		
				if(-1 == unlink(pDb))			//rm emu.db
					printf("%s\n","emu.db delete failer!");
				return -1;
			}
		}

		for(_i = 0;_i < sizeof(T_init)/sizeof(T_init[0]);_i++)	//Initialize Table
		{
			if(-1 == Db_ExecSql(hdb,T_init[_i])) 
			{
				printf("Function:%s-->Db_ExecSql error! \n",__FUNCTION__);
				return -1;
			}
		}
#if 0		
		sprintf(_pSql,"SELECT * FROM T_Invlist");
		printf("%s\r\n",_pSql);
		_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
		if(SQLITE_OK == _result)
		{
			int _j = 0,_index = _nColumn;;
			for(_i = 0;_i < _nRow;_i++)
			{
				for(_j =0 ;_j < _nColumn;_j++)
				{
					printf("%s\n",_dbResult[_index]);
					_index++;
				}
			}
		}
		sqlite3_free_table(_dbResult);
		while(1)
		{
			printf("ok!!!!!!!!!!!!!!!!!!!!!!\n");
			sleep(1);
		}
#endif
	}
	Db_Update_Init();
	return 0;
}

/****************************************************/
//FuncName : Db_Update
//Description :
//	Update the DB
//Input : 
//	->pPLC_Dat_: Pointer to struct pPLC_Dat_ which is got via PLC
//	->bUpdat_T_Statlist_:
//		->1:Update T_statlist Table in DB 
//		->0:Not do this
//	->Cur_time_:
//		->Current time
//Return :
//	->-1: Failed
//	->0: Success
//SideEffect : None
/****************************************************/
int	Db_Update(struct PLC_Dat *pPLC_Dat_,int bUpdat_T_Statlist_,
												struct tm *pCur_time_)
{
	//printf("Function:%s",__FUNCTION__);
	
	char _pSql[100] = {0};
	uint _i = 0;
	
	static	struct tm _last_time;

	ullint	_life_worktime_before_thisConnct = 0,_this_conctTime = 0,_life_worktime = 0;
	ullint	_Power_Before_Today = 0,_Power_Before_Week = 0,_Power_Before_Month = 0;

	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;

	//Invt Table
	sprintf(_pSql,"UPDATE T_Invlist SET Cur_Tmpr=%hd, Life_Power=%d ,Cur_Watt=%d,Date = strftime('%%s','now','localtime') WHERE Invt_Adr=%llu;",pPLC_Dat_->Cur_Tmpr,pPLC_Dat_->Life_Power,pPLC_Dat_->Cur_Watt,pPLC_Dat_->Invt_Adr);
	if(-1 == Db_ExecSql(hdb,_pSql))
		printf("Function: %s error\n",__FUNCTION__);


	//Event Table
	if(-1 == Db_IsRecordExist(pPLC_Dat_,EVTTBL,EvtArry))	
	{
		if(-1 == Db_InsertRecord(pPLC_Dat_,EVTTBL,EvtArry))
		{
			printf("Function: %s error\n",__FUNCTION__);
		}
	}
	for(_i = 0;_i < EVT_MAXCOUNT;_i++)
	{
		if(0 == ((pPLC_Dat_->state) & (1<<_i)) )
		{
			sprintf(_pSql,"SELECT * from T_Evtlist WHERE Event_Id=%d;",_i);
			_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
			if(SQLITE_OK == _result)
			{
				sprintf(_pSql,"DELETE from T_Evtlist WHERE Event_Id=%d;",_i);
				if(-1 == Db_ExecSql(hdb,_pSql))
					printf("Function: %s error\n",__FUNCTION__);
			}
		}
	}


	//T_Statlist
	if(1 == bUpdat_T_Statlist_)			
	{
		time_t	_time_t = mktime(pCur_time_);

		sprintf(_pSql,"SELECT Life_Worktime_Before_ThisConnct, This_ConctTime from T_Inerlist");
		_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
		if(SQLITE_OK == _result)
		{
			assert(_nRow == 1);
			_life_worktime_before_thisConnct = atoll(_dbResult[_nColumn]);
			_this_conctTime = atoll(_dbResult[_nColumn+1]);
		}
		_life_worktime = _life_worktime_before_thisConnct + (ullint)_time_t - _this_conctTime;
		sprintf(_pSql,"UPDATE T_Statlist SET Life_Worktime = %llu",_life_worktime);
		if(-1 == Db_ExecSql(hdb,_pSql))			//Connect_Time has been updated in "Db_Update_Init()"
			printf("Function: %s error\n",__FUNCTION__);
	}

	//T_FixInvlist Table Should be not updated here


	//T_Inerlist
	if(pCur_time_->tm_mon != _last_time.tm_mon)	//The next month
	{
		_last_time.tm_mon = pCur_time_->tm_mon;
		sprintf(_pSql,"SELECT SUM(Life_Power) AS Life_Power from T_Invlist");
		_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
		if(SQLITE_OK == _result)
		{
			assert(_nRow == 1);
			_Power_Before_Month = atoll(_dbResult[_nColumn]);
		}

		sprintf(_pSql,"UPDATE T_Inerlist SET Power_Before_Month = %llu;",_Power_Before_Month);
		if(-1 == Db_ExecSql(hdb,_pSql))
			printf("Function: %s error\n",__FUNCTION__);
	}

	
	if(pCur_time_->tm_wday != _last_time.tm_wday)	//The next week
	{
		_last_time.tm_wday = pCur_time_->tm_wday;
		sprintf(_pSql,"SELECT SUM(Life_Power) AS Life_Power from T_Invlist");
		_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
		if(SQLITE_OK == _result)
		{
			assert(_nRow == 1);
			_Power_Before_Week = atoll(_dbResult[_nColumn]);
		}

		sprintf(_pSql,"UPDATE T_Inerlist SET Power_Before_Week = %llu;",_Power_Before_Week);
		if(-1 == Db_ExecSql(hdb,_pSql))
			printf("Function: %s error\n",__FUNCTION__);
	}


	if(pCur_time_->tm_mday != _last_time.tm_mday)	//The next week
	{
		_last_time.tm_mday = pCur_time_->tm_mday;
		sprintf(_pSql,"SELECT SUM(Life_Power) AS Life_Power from T_Invlist");
		_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
		if(SQLITE_OK == _result)
		{
			assert(_nRow == 1);
			_Power_Before_Today = atoll(_dbResult[_nColumn]);
		}

		sprintf(_pSql,"UPDATE T_Inerlist SET Power_Before_Today = %llu;",_Power_Before_Today);
		if(-1 == Db_ExecSql(hdb,_pSql))
			printf("Function: %s error\n",__FUNCTION__);
	}
	return 0;
}


/****************************************************/
//FuncName : Db_Get_SocketDat
//Description :
//	Read data used for socket communication from DB
//Input : None
//Return :None
//SideEffect : None
/****************************************************/
void	Db_Get_SocketDat()
{
	//printf("Function:%s",__FUNCTION__);
/*
	memset(pEmu_Scoket_,0,sizeof(struct Emu_Socket));
	pEmu_Scoket_->Dat_Start = 0x68;
	
	char _pSql[100] = {0};
	char _pSql1[100] = {0};
	int _i = 0,_j = 0;
	struct	stat _Sdstate;

	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;

	char **_dbResult1;		//for sqlite operation
	int _nRow1,_nColumn1,_result1;
	char * _errmsg1 = NULL;

//-------------------------------------------------------------------------
	sprintf(_pSql,"SELECT SUM(Life_Power) AS Life_Power,SUM(Cur_Watt) AS Cur_Watt FROM T_Invlist;");
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Life_Power = atoi(_dbResult[_nColumn]);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Cur_Watt = atoi(_dbResult[_nColumn+1]);
	}
	sqlite3_free_table(_dbResult);

	sprintf(_pSql,"SELECT Power_Before_Today,Power_Before_Week,Power_Before_Month FROM T_Inerlist;");
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Day_Power = \
					pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Life_Power - atoi(_dbResult[_nColumn]);

		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Week_Power= \
					pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Life_Power - atoi(_dbResult[_nColumn+1]);

		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Month_Power= \
					pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Life_Power - atoi(_dbResult[_nColumn+2]);
	}
	sqlite3_free_table(_dbResult);

	
	sprintf(_pSql,"SELECT Last_ConctTime,Life_Worktime,Totl_Invt_Counts,Online_Invt_Counts,SigStrth FROM T_Statlist;");
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Connect_Time = atoll(_dbResult[_nColumn]);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Life_Time = atoll(_dbResult[_nColumn+1]);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Totl_Invt_Counts = atoi(_dbResult[_nColumn+2]);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Online_Invt_Counts = atoi(_dbResult[_nColumn+3]);
		pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.SigStrth = atoi(_dbResult[_nColumn+4]);
	}	
	sqlite3_free_table(_dbResult);

	if(-1 == stat(pDb,&_Sdstate))
	{
		printf("Function:%s--->Line:%d Error",__FUNCTION__,__LINE__);
	}
	pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Sd_Percent = 100*(_Sdstate.st_size)/SD_SIZE;

	//If we need or not?
	pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Mac = 0;
	pEmu_Scoket_->emu_dat.emu_socket_dat.dat_statstc.Last_Week_Power = 0;

//-------------------------------------------------------------------------
	sprintf(_pSql,"SELECT * FROM T_Invlist;");
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		for(_i = 0;_i < _nRow;_i++)		//Inverter's Counts
		{
			pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Invt_Adr = atoll(_dbResult[_nColumn]);
			pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Cur_Tmpr = atoi(_dbResult[_nColumn+1]);
			pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Life_Power = atoi(_dbResult[_nColumn+2]);
			pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Cur_Watt = atoi(_dbResult[_nColumn+3]);
			pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Send_Time = atoll(_dbResult[_nColumn+4]);

			//T_Evtlist
			sprintf(_pSql1,"SELECT Event_Id,Date FROM T_Evtlist WHERE Invt_Adr=%llu;",pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Invt_Adr);
			_result1 = sqlite3_get_table(hdb, _pSql1, &_dbResult1, &_nRow1, &_nColumn1, &_errmsg1);
			if(SQLITE_OK == _result1)
			{
				pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].bEvent = 1;
				for(_j = 0;_j < _nRow1;_j++)		//Event's Counts
				{
					pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Invt_Event[_j].Event_Id = atoi(_dbResult1[_nColumn1]);
					pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Invt_Event[_j].Event_Time = atoll(_dbResult1[_nColumn1+1]);
				}
			}
			else
				pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].bEvent = 0;
			sqlite3_free_table(_dbResult1);


			//T_FixInvlist
			sprintf(_pSql1,"SELECT * FROM T_FixInvlist WHERE Invt_Adr=%llu;",pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Invt_Adr);
			_result1 = sqlite3_get_table(hdb, _pSql1, &_dbResult1, &_nRow1, &_nColumn1, &_errmsg1);
			if(SQLITE_OK == _result1)
			{
				pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].type = atoi(_dbResult[_nColumn1+1]);
				pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].FixTime = atoll(_dbResult[_nColumn+2]);
				pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Hard_Version = atoi(_dbResult[_nColumn+3]);
				pEmu_Scoket_->emu_dat.emu_socket_dat.invt_spec[_i].Firm_Version = atoi(_dbResult[_nColumn+4]);
			}
			else
				Debug_Info();

			sqlite3_free_table(_dbResult1);
		}
	}
	sqlite3_free_table(_dbResult);
*/
}


/****************************************************/
//FuncName : Db_Update_Init
//Description :
//	->Update the DB When Init
//	->Called by "Db_Init()" Function
//Input : None
//Return :None
//SideEffect : None
/****************************************************/
void	Db_Update_Init()
{
	char _pSql[100] = {0};
	unsigned long long int _time,_life_worktime;

	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;

	sprintf(_pSql,"SELECT This_ConctTime FROM T_Inerlist;");	
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		_time = atoll(_dbResult[_nColumn]);
	}
	sprintf(_pSql,"UPDATE T_Statlist SET Last_ConctTime = %llu;",_time);	
	if(-1 == Db_ExecSql(hdb,_pSql))
		printf("Function: %s error\n",__FUNCTION__);	

	sprintf(_pSql,"SELECT Life_Worktime FROM T_Statlist;");	
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		_life_worktime = atoll(_dbResult[_nColumn]);
	}

	sprintf(_pSql,"UPDATE T_Inerlist SET Life_Worktime_Before_ThisConnct = %llu, \
					This_ConctTime = strftime('%%s','now','localtime');",_life_worktime);	
	if(-1 == Db_ExecSql(hdb,_pSql))
		printf("Function: %s error\n",__FUNCTION__);

	sqlite3_free_table(_dbResult);
}


/****************************************************/
//FuncName : Db_Rdfstsettime
//Description :
//	Query DB To see if this is the fst time to set time
//Input : None
//Return :
//	->0: YES
//	->-1: NO
//SideEffect : None
/****************************************************/
int		Db_Rdfstsettime()
{
	//printf("%s\n",__FUNCTION__);

	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;	
	int _index = 0,_ret = -1;
	
	_result = sqlite3_get_table(hdb, "select FstSettime from T_Inerlist;", &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		_index = _nColumn;
		if(1 == atoi(_dbResult[_index]))
			_ret = 0;
#if 0 
		printf("%d\n",_ret);
		printf("%d\n",_ret);
		
		int _j = 0,_i = 0;
		for(_i = 0;_i < _nRow;_i++)
		{
			_index = _nColumn;
			for(_j =0 ;_j < _nColumn;_j++)
			{
				printf("%s\n",_dbResult[_index]);
				_index++;
			}
		}
#endif
	}
	
	sqlite3_free_table( _dbResult);
	return _ret;
}

/****************************************************/
//FuncName : Db_Clrfstsetttime
//Description :
//	Clear the fst settime flag in DB
//Input : None
//Return :None
//SideEffect : None
/****************************************************/
void	Db_Clrfstsetttime()
{
	printf("%s\n",__FUNCTION__);

	char _psql[100];
	sprintf(_psql, "UPDATE T_Inerlist SET FstSettime=0;");
	if(-1 == Db_ExecSql(hdb,_psql))
		printf("Function: %s error\n",__FUNCTION__);
}
/****************************************************/
//FuncName : Db_Rdfststartup
//Description :
//	Read the fst startup flag in DB
//Input : None
//Return :
//	->0: YES
//	->-1: NO
//SideEffect : None
/****************************************************/
int		Db_Rdfststartup()
{
	//printf("%s\n",__FUNCTION__);

	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;	
	int _index,_ret = -1;
	
	_result = sqlite3_get_table(hdb, "SELECT FstStart FROM T_Inerlist;", &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		_index = _nColumn;
		if(atoi(_dbResult[_index]) == 1)
			_ret = 0;
		
#if 0
		printf("%d\n",_ret);
		printf("%d\n",_ret);
		
		int _j = 0,_i = 0;
		for(_i = 0;_i < _nRow;_i++)
		{
			for(_j =0 ;_j < _nColumn;_j++)
			{
				printf("%s\n",_dbResult[_index]);
				_index++;
			}
		}
#endif
		
	}
	sqlite3_free_table(_dbResult);
	return _ret;
}
/****************************************************/
//FuncName : Db_Clrfstsetttime
//Description :
//	Clear the fst startup flag in DB
//Input : None
//Return :None
//SideEffect : None
/****************************************************/
void	Db_Clrfststartup()
{
	//printf("%s\n",__FUNCTION__);

	char _psql[100];
	sprintf(_psql, "UPDATE T_Inerlist SET FstStart=0;");
	if(-1 == Db_ExecSql(hdb,_psql))
		printf("Function: %s error\n",__FUNCTION__);
}

/****************************************************/
//FuncName : Db_IsRecordExist
//Description :
//Input : 
//	->pPLC_Dat_: Pointer to struct pPLC_Dat_ which is got via PLC
//	->tablename_: Table's Name in DB
//	->pEvtAry_: Array Pointer Pointing to array where record error which is occured but not writed to DB
//		Only used in "EVTTBL" Table in DB, Such as *(pEvtAry_+1) ==1, then the NO.1 error occured but not recorded
//Return :
//	->0: Exist
//	->-1: Not Exist
//SideEffect : None
/****************************************************/
int		Db_IsRecordExist(struct	PLC_Dat *pPLC_Dat_,enum TableName tablename_,unsigned char *pEvtAry_)
{
	char _psql[100] = {0};
	int	_ret = 0,_i = 0;

	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;
	switch(tablename_)
	{
		case INVTTBL:
		{
			sprintf(_psql,"select * from T_Invlist where Invt_Adr=%llu;",pPLC_Dat_->Invt_Adr);
		}break;
		case EVTTBL:	//Process Separately for one InvAdr may have several Evt
		{
			assert(pEvtAry_!=NULL);
			memset(pEvtAry_,0,sizeof(pEvtAry_));
			for(_i = 0;_i < EVT_MAXCOUNT;_i++)
			{
				if(((pPLC_Dat_->state) & (1<<_i)) != 0)
				{
					sprintf(_psql,"select * from T_Evtlist where Invt_Adr=%llu AND Event_Id=%d;",pPLC_Dat_->Invt_Adr,_i);

					_result = sqlite3_get_table(hdb, _psql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
					if(SQLITE_OK != _result)
					{
						*(pEvtAry_+_i) = 1;
					}
				}
			}
			
			for(_i = 0;_i < EVT_MAXCOUNT;_i++)
			{
				if(1 == pEvtAry_[_i])
				{
					_ret = -1;
					break;
				}
			}
			sqlite3_free_table( _dbResult);
			return _ret;
		}break;
		case FIXINVTTBL:
		{
			sprintf(_psql,"SELECT * FROM T_FixInvlist WHERE Invt_Adr=%llu;",pPLC_Dat_->Invt_Adr);
		}break;
	}
	_result = sqlite3_get_table(hdb,_psql,&_dbResult,&_nRow,&_nColumn,&_errmsg);
	if(SQLITE_OK != _result)
		_ret = -1;
	sqlite3_free_table(_dbResult);
	return _ret;
}

/****************************************************/
//FuncName : Db_InsertRecord
//Description :
//Input : 
//	->pPLC_Dat_: Pointer to struct pPLC_Dat_ which is got via PLC
//	->tablename_: Table's Name in DB
//	->pEvtAry_:Array Pointer Pointing to array where record error which is occured but not writed to DB
//		Only used in "EVTTBL" Table in DB, Such as *(pEvtAry_+1) ==1, then the NO.1 error occured but not recorded
//Return :
//	->0: Success
//	->-1: Failure
//SideEffect : None
/****************************************************/
int 	Db_InsertRecord(struct PLC_Dat *pPLC_Dat_,enum TableName tablename_,unsigned char *pEvtAry_)
{
	int _i,_ret = 0;
	char _psql[100] = {0};
	
	switch(tablename_)
	{
		case INVTTBL:
		{
			sprintf(_psql,"INSERT into T_Invlist values(%llu,%hd,%d,%d,strftime('%%s','now','localtime'));",pPLC_Dat_->Invt_Adr,pPLC_Dat_->Cur_Tmpr,pPLC_Dat_->Life_Power,pPLC_Dat_->Cur_Watt);
			if(-1 == Db_ExecSql(hdb,_psql))
				_ret = -1;
		}break;
		case EVTTBL:
		{
			assert(pEvtAry_!=NULL);
			for(_i = 0; _i < EVT_MAXCOUNT;_i++)	
			{
				if(pEvtAry_[_i] != 0)
				{
					sprintf(_psql,"INSERT into T_Evtlist values(%llu,%d,strftime('%%s','now','localtime'));",pPLC_Dat_->Invt_Adr,_i);
					if(-1 == Db_ExecSql(hdb,_psql))
						_ret = -1;
				}
			}
		}break;
		case FIXINVTTBL:
		{
			sprintf(_psql,"INSERT into T_FixInvlist values(%llu,%d,%llu,%hd,%hd);",	\
					pPLC_Dat_->Invt_Adr,pPLC_Dat_->type,pPLC_Dat_->FixTime,pPLC_Dat_->Hard_Version,pPLC_Dat_->Firm_Version);
			if(-1 == Db_ExecSql(hdb,_psql))
				_ret = -1;		
		}break;
	}
	return _ret;
}

/****************************************************/
//FuncName : Db_Get_InvtAdr
//Description :
//Input : 
//	->pInvtAdr_:Pointer to The Array of the InvAdr
//Return : 
//	->Inverter Count
//SideEffect : 
/****************************************************/
int		Db_Get_InvtAdr(ullint *pInvtAdr_)
{
	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;	
	int _index,_i = 0,_j = 0,_k = 0;

	assert(0 != pInvtAdr_);
	memset(pInvtAdr_,0,sizeof(pInvtAdr_));
	_result = sqlite3_get_table(hdb, "SELECT Invt_Adr FROM T_Invlist;", &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		_index = _nColumn;
		for(_i = 0;_i < _nRow;_i++)
		{
			for(_j = 0;_j < _nColumn;_j++)
			{
				pInvtAdr_[_k++] = atoll(_dbResult[_index]);
				assert(_k <= INVT_MAXCOUNT);
				_index++;
			}
		}
	}
	sqlite3_free_table( _dbResult);
	return _nRow;
}


/****************************************************/
//FuncName : Db_Get_LcdkeyDat
//Description :
//Input : 
//	->pDb2LcdKey_:Pointer to Struct of Db2LcdKey
//Return : 
//	->0:  Success
//	->-1: Failed
//SideEffect : 
/****************************************************/
int		Db_Get_LcdkeyDat(struct Db2LcdKey* pDb2LcdKey_)
{
	//printf("%s\n",__FUNCTION__);

	char _pSql[100] = {0};
	
	char **_dbResult;		//for sqlite operation
	int	_nRow,_nColumn,_result;
	char * _errmsg = NULL;

	sprintf(_pSql,"SELECT SUM(Cur_Watt) AS Cur_Watt ,SUM(Life_Power) AS Life_Power FROM T_Invlist;");
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		pDb2LcdKey_->Cur_Watt = atoi(_dbResult[_nColumn]);
		pDb2LcdKey_->Life_Power = atoi(_dbResult[_nColumn+1]);
	}
	sqlite3_free_table( _dbResult);
	
	sprintf(_pSql,"SELECT Online_Invt_Counts FROM T_Statlist;");
	_result = sqlite3_get_table(hdb, _pSql, &_dbResult, &_nRow, &_nColumn, &_errmsg);
	if(SQLITE_OK == _result)
	{
		assert(_nRow == 1);
		pDb2LcdKey_->Online_Invt_Counts = atoi(_dbResult[_nColumn]);
	}
	sqlite3_free_table( _dbResult);

	return 0;
}


/****************************************************/
//FuncName : Db_open
//Description :
//	->Open DB
//Input : 
//	->pdb_:The DB file's PATH
//	->hdb_:The DB file's Handle
//Return : 
//	->0: Success
//	->-1:Failed
//SideEffect : 
//	->None
/****************************************************/
int		Db_open(const char *pdb_, sqlite3** hdb_)
{
	if(SQLITE_OK == sqlite3_open(pdb_, hdb_))
		return 0;
	else
		 return -1;
}
 
/****************************************************/
//FuncName : Db_ExecSql
//Description :
//		Excecute SQL statement 
//Input : 
//	->psql_:the SQL statement to be excecuted
//	->hdb_:The DB file's Handle
//Return : 
//	->0: Success
//	->-1:Failed
/****************************************************/
int		Db_ExecSql(sqlite3* hdb_,char * psql_)
{
	//printf("%s\r\n",psql_);

	char * _errmsg;
	sqlite3_exec(hdb_,psql_,0,0,&_errmsg);

	if(NULL != _errmsg)
	{
		printf("errmsg:%s\r\n",_errmsg);
		return -1;
	}
	return 0;
 }

/****************************************************/
//FuncName : Db_close
//Description :
//		Close DB
//Input : 
//	->hdb_:The DB file's Handle
//Return : 
//	->0: Success
//	->-1:Failed
/****************************************************/
int		Db_close(sqlite3* hdb_)
{
	if(SQLITE_OK == sqlite3_close(hdb_))
		return -1;
	return 0;
}


int		Db_Test()
{

}

